import re
import os
import shutil
import glob  # Import glob module properly
# from glob import glob
from tempfile import NamedTemporaryFile
import itertools
import subprocess
from pathlib import Path
import sys

def preprocess(filename):
    # 处理注释和跨行连接符
    with open(filename, 'r+') as f:
        content = f.read()
        # 删除回车符
        content = content.replace('\r', '')
        # 处理注释符号
        content = re.sub(r'^[ \t]*!.*\n?', '', content, flags=re.MULTILINE)
        # 处理跨行连接符 &
        lines = content.split('\n')
        new_lines = []
        i = 0
        while i < len(lines):
            line = lines[i]
            while '&' in line:
                line = line.replace('&', '').rstrip()
                i += 1
                if i < len(lines):
                    line += lines[i].lstrip()
            new_lines.append(line)
            i += 1
        content = '\n'.join(new_lines)
        # 写回文件
        f.seek(0)
        f.write(content)
        f.truncate()
    print("preprocess complete")

def proc_real_dim(filename):
    # 处理real dimension声明
    varmap = []
    with open(filename, 'r') as f:
        lines = f.readlines()
    
    new_lines = []
    with open(filename + '.varmap.double', 'w') as vf:
        for line in lines:
            match = re.match(r'(?i)^\s*real\s*.*dimension\s*\([^()]*\).*::', line)
            if match:
                parts = re.split(r'::', line, 1)
                dim_part = re.search(r'(?i)dimension\s*\(([^)]*)', parts[0]).group(1)
                vars_part = parts[1].strip()
                vars_list = [v.strip().lower() for v in vars_part.split(',')]
                new_line = f"\tdouble {', '.join(vars_list)}{dim_part};\n"
                new_lines.append(new_line)
                vf.write('\n'.join(vars_list) + '\n')
            else:
                new_lines.append(line)
    
    with open(filename, 'w') as f:
        f.writelines(new_lines)
    print("proc_real_dim complete")

def proc_find_call(filename):
    # 查找函数调用
    calls = set()
    with open(filename, 'r') as f:
        for line in f:
            match = re.search(r'(?i)^\s*call\s+([a-z]\w*)', line)
            if match:
                calls.add(match.group(1).lower())
    
    with open(filename + '.call', 'w') as f:
        f.write('\n'.join(sorted(calls)))
    print("proc_find_call complete")

def proc_find_allvar(filename):
    # 查找所有变量
    s1 = r'(?i)'
    s1 = r'(\W|^)'
    variables = set()
    with open(filename, 'r') as f:
        for line in f:
            if re.search(r'(?i)write|subroutine|integer|real|private|deallocate|allocate|//', line):
                continue
            matches = re.findall(r'(?i)([a-z_]\w*)\s*\(', line)
            for var in matches:
                var = var.lower().replace('=', '').strip()
                if var not in ('if', 'type', 'intent'):
                    variables.add(var)
    
    # 排除函数调用
    with open(filename + '.call', 'r') as f:
        calls = set(f.read().splitlines())
    
    variables -= calls
    with open(filename + '.varlist', 'w') as f:
        f.write('\n'.join(sorted(variables)))
    print("proc_find_allvar complete")


def proc_allocate(f_file):
    try:
        # Get module files from USE statements
        obj_path = os.path.join('output', f_file)
        with open(obj_path, 'r') as f:
            content = f.read()
        
        # Find all USE statements
        use_modules = set()
        for match in re.finditer(r'^\s*use\s+(\w+)', content, re.I | re.M):
            use_modules.add(match.group(1).lower() + '.F90')
        
        # Copy module files
        tmp_dir = 'output'
        for module in use_modules:
            if os.path.exists(module):
                shutil.copy(module, tmp_dir)
        
        # Process files in tmp
        os.chdir(tmp_dir)
        for fname in use_modules:
            if not os.path.exists(fname):
                continue
            
            # Remove comments and clean content
            with open(fname, 'r') as f:
                content = f.read()
            
            # Remove comments
            content = re.sub(r'^\s*!.*', '', content, flags=re.M)
            content = re.sub(r'!(?!<).*', '', content)
            content = content.replace('\r', '')
            
            # Handle line continuations
            content = re.sub(r'&\s*\n\s*', '', content)
            
            # Remove everything after CONTAINS
            contains_match = re.search(r'^\s*contains\s*$', content, re.I | re.M)
            if contains_match:
                content = content[:contains_match.start()]
            
            with open(fname, 'w') as f:
                f.write(content)
        
        # Process variable allocations
        varlist_path = f'{f_file}.varlist'
        with open(varlist_path, 'r') as f:
            variables = [line.strip() for line in f if line.strip()]
        
        # Create temporary files
        tmp_files = []
        for var in variables:
            # Process variable dimensions
            var_pattern = re.compile(rf'\b{var}\s*\([^()]*\)', re.I)
            
            # Search in module files
            for mod_file in use_modules:
                if not os.path.exists(mod_file):
                    continue
                
                with open(mod_file, 'r') as f:
                    mod_content = f.read()
                
                # Find allocations and declarations
                alloc_matches = re.finditer(
                    rf'^\s*allocate\s*\(.*{var}\s*\([^()]*\).*\)', 
                    mod_content, 
                    re.I | re.M
                )
                
                decl_matches = re.finditer(
                    rf'^\s*(integer|real|dimension)\s+.*\b{var}\b', 
                    mod_content, 
                    re.I | re.M
                )
                
                # Write to temporary files
                with NamedTemporaryFile(mode='w+', delete=False) as tmp:
                    for match in itertools.chain(alloc_matches, decl_matches):
                        line = match.group()
                        # Process dimension patterns
                        dim_match = re.search(rf'dimension\s*\(([^()]*)\)', line, re.I)
                        if dim_match:
                            dims = dim_match.group(1)
                            tmp.write(f'_mp_{var}_{dims}\n')
                        else:
                            tmp.write(f'_mp_{var}_\n')
                    tmp_files.append(tmp.name)
        
        # Merge and process temporary files
        varmap_path = f'{f_file}.varmap'
        with open(varmap_path, 'w') as out_f:
            seen = set()
            for tmp in tmp_files:
                with open(tmp, 'r') as in_f:
                    for line in in_f:
                        clean_line = line.strip().lower()
                        if clean_line not in seen:
                            seen.add(clean_line)
                            out_f.write(line)
                os.remove(tmp)
        
        os.chdir('..')
        print("proc_allocate complete")
    except Exception as e:
        log_error(f"proc_allocate error: {str(e)}")

def proc_varfile_map(f_file):
    try:
        varlist_path = os.path.join('output', f'{f_file}.varlist')
        varmap_path = os.path.join('output', f'{f_file}.varmap')
        varin_path = os.path.join('output', f'{f_file}.varin')
        varout_path = os.path.join('output', f'{f_file}.varout')
        
        with open(varlist_path, 'r') as f:
            variables = [line.strip() for line in f]
        
        # Create variable mappings
        var_mappings = {}
        with open(varmap_path, 'r') as f:
            for line in f:
                parts = line.strip().split('_')
                if len(parts) >= 4:
                    orig_var = parts[2]
                    var_mappings[orig_var.lower()] = line.strip().lower()
        
        # Separate internal/external variables
        external_vars = set(var_mappings.keys())
        internal_vars = set(variables) - external_vars
        
        # Write output files
        with open(varout_path, 'w') as f:
            for var in external_vars:
                f.write(f'{var_mappings[var]}\n')
        
        with open(varin_path, 'w') as f:
            for var in internal_vars:
                f.write(f'{var}\n')
        
        print("proc_varfile_map complete")
    except Exception as e:
        log_error(f"proc_varfile_map error: {str(e)}")

def proc_varname(f_file):
    try:
        obj_path = os.path.join('output', f_file)
        varout_path = os.path.join('output', f'{f_file}.varout')
        varmap_path = os.path.join('output', f'{f_file}.varmap')
        varin_path = os.path.join('output', f'{f_file}.varin')
        
        # Load variable mappings
        var_mappings = {}
        with open(varmap_path, 'r') as f:
            for line in f:
                parts = line.strip().split('_')
                if len(parts) >= 3:
                    orig_var = parts[2].lower()
                    var_mappings[orig_var] = line.strip().lower()
        
        # Load variables to modify
        with open(varout_path, 'r') as f:
            replace_vars = [line.strip() for line in f]
        
        with open(varin_path, 'r') as f:
            append_vars = [line.strip() for line in f]
        
        # Process file content
        with open(obj_path, 'r') as f:
            content = f.read()
        
        # Build regex patterns
        patterns = []
        # Replacement for external variables
        for orig, mapped in var_mappings.items():
            patterns.append((re.compile(rf'(\W){orig}(\W|$)', re.I), rf'\1{mapped}\2'))
        
        # Append suffix for internal variables
        for var in append_vars:
            patterns.append((re.compile(rf'(\W){var}(\W|$)', re.I), rf'\1{var}_\2'))
        
        # Apply all replacements
        for pattern, replacement in patterns:
            content = pattern.sub(replacement, content)
        
        # Write modified content back
        with open(obj_path, 'w') as f:
            f.write(content)
        
        print("proc_varname complete")
    except Exception as e:
        log_error(f"proc_varname error: {str(e)}")

import re
import os
from pathlib import Path

def proc_do(f_file):
    try:
        obj_path = os.path.join('output', f_file)
        temp_path = os.path.join('output', f_file + '.copy.tmp')
        
        # Read original content
        with open(obj_path, 'r') as f:
            content = f.read()

        # Phase 1: Parameter reordering and index adjustment
        # Define regex patterns for parameter substitution
        param_patterns = [
            (re.compile(r'_\(([^,]+),([^,]+),([^,]+),([^,]+),([^)]+)\)', re.I), 
             r'_[\5][\4][\3][\2][\1]'),
            (re.compile(r'_\(([^,]+),([^,]+),([^,]+),([^)]+)\)', re.I), 
             r'_[\4][\3][\2][\1]'),
            (re.compile(r'_\(([^,]+),([^,]+),([^)]+)\)', re.I), 
             r'_[\3][\2][\1]'),
            (re.compile(r'_\(([^,]+),([^)]+)\)', re.I), 
             r'_[\2][\1]'),
            (re.compile(r'_\(([^)]+)\)', re.I), 
             r'_[\1]')
        ]

        # Apply parameter substitutions
        modified = content
        for pattern, replacement in param_patterns:
            modified = pattern.sub(replacement, modified)

        # Adjust numeric indices [N] to [N-1]
        index_adjust = re.compile(r'\[([0-9]+)\]')
        modified = index_adjust.sub(lambda m: f'[{int(m.group(1))-1}]', modified)

        # Save intermediate result
        with open(temp_path, 'w') as f:
            f.write(modified)

        # Phase 2: Convert DO loops to for loops
        output = []
        for line in modified.split('\n'):
            if not re.match(r'^\s*do\s', line, re.I):
                output.append(line)
                continue
                
            # Parse DO statement
            parts = re.split(r'\bdo\s+|\s*=\s*|\s*,\s*', line, flags=re.I)
            parts = [p.strip() for p in parts if p.strip()]
            
            if len(parts) < 4:
                output.append(line)
                continue

            var = parts[1]
            start = parts[2]
            end = parts[3]
            step = parts[4] if len(parts) > 4 else '1'

            # Convert step syntax
            if re.match(r'^\d+$', step):
                step_op = f'+{step}'
            elif step.startswith('-'):
                step_op = f'-{step[1:]}'
            else:
                step_op = f'+{step}'

            # Generate C-style for loop
            if step == '1':
                loop = (
                    f"{parts[0]}for ({var} = {start}-1; {var} < {end}; {var}++) {{"
                )
            else:
                loop = (
                    f"{parts[0]}for ({var} = {start}-1; {var} < {end}; {var} += {step}) {{"
                )
            
            output.append(loop)

        # Write converted content
        with open(obj_path, 'w') as f:
            f.write('\n'.join(output))

        # Phase 3: Generate validation conditionals
        condition_output = []
        with open(temp_path, 'r') as f:
            temp_content = f.read()

        for line in temp_content.split('\n'):
            if not re.match(r'^\s*do\s', line, re.I):
                condition_output.append(line)
                continue
                
            parts = re.split(r'\bdo\s+|\s*=\s*|\s*,\s*', line, flags=re.I)
            parts = [p.strip() for p in parts if p.strip()]
            
            if len(parts) < 4:
                condition_output.append(line)
                continue

            var = parts[1]
            start = parts[2]
            end = parts[3]
            step = parts[4] if len(parts) > 4 else '1'

            # Generate validation condition
            if step == '1':
                cond = (
                    f"{parts[0]}if ({var} >= {start}-1 && {var} < {end}) {{"
                )
            else:
                cond = (
                    f"{parts[0]}if (({step} > 0 && {var} >= {start}-1 && {var} < {end}) || "
                    f"({step} < 0 && {var} <= {start}-1 && {var} > {end})) {{"
                )
            
            condition_output.append(cond)

        # Write conditionals to original file (modify as needed)
        # This part depends on how you want to integrate the conditionals
        # For demonstration, we'll append to a new file
        cond_path = os.path.join('output', f_file + '.conditions')
        with open(cond_path, 'w') as f:
            f.write('\n'.join(condition_output))

        # Cleanup temporary files
        os.remove(temp_path)
        print("proc_do complete")

    except Exception as e:
        print(f"Error in proc_do: {str(e)}")
        if Path(temp_path).exists():
            os.remove(temp_path)



def proc_pos_include(filename):
    # 处理头文件包含位置
    with open(filename, 'r+') as f:
        lines = f.readlines()
        new_lines = []
        i = 0
        while i < len(lines):
            line = lines[i]
            if re.match(r'(?i)^\s*(subroutine|program)\s+', line):
                # 找到子程序声明后的第一个非注释行
                first_line = line
                j = i + 1
                while j < len(lines) and re.match(r'^\s*[#/]', lines[j]):
                    j += 1
                # 插入到合适位置
                new_lines.insert(j, first_line)
                new_lines.append(lines[i+1:j] + [lines[i]])
                i = j
            else:
                new_lines.append(line)
                i += 1
        f.seek(0)
        f.writelines(new_lines)
        f.truncate()

import re
import os
import shutil
from glob import glob

def process_subroutine(match):
    """Process Fortran subroutine lines into C function declarations"""
    name = match.group(1).lower()
    params = match.group(3).strip() if match.group(3) else ''
    return f'extern void {name}_({params}){{\n'

def proc_f2c(filename):
    # Define regex patterns for substitutions
    patterns = [
        (r'program\\s+\\w+', 'void main()'),
        (r'subroutine\\s+(\\w+)\\s*\\(([^)]*)\\)', r'extern void \\1_(\\2);'),
        (r'end\\s+subroutine', '}'),
        (r'real\\s*\\(\\s*kind\\s*=\\s*8\\s*\\)\\s*,\\s*dimension\\s*\\(([^)]+)\\)\\s*::\\s*(\\w+)', r'double \\2[\\1];'),
        (r'integer\\s*,\\s*dimension\\s*\\(([^)]+)\\)\\s*::\\s*(\\w+)', r'int \\2[\\1];'),
        (r'real\\s*\\(\\s*kind\\s*=\\s*8\\s*\\)', 'double'),
        (r'\\bdo\\s+(\\w+)\\s*=\\s*(\\w+)\\s*,\\s*(\\w+)\\s*,\\s*(\\w+)', r'for(\\1=\\2-1;\\1<\\3;\\1+=\\4)'),
        (r'\\bdo\\s+(\\w+)\\s*=\\s*(\\w+)\\s*,\\s*(\\w+)', r'for(\\1=\\2-1;\\1<\\3;\\1++)'),
        (r'end\\s+do', '}'),
        (r'if\\s*\\(([^)]+)\\)\\s*then', r'if(\\1){'),
        (r'end\\s+if', '}'),
        (r'else', 'else'),
        (r'\\bmin\\s*\\(', 'min_('),
        (r'\\bmax\\s*\\(', 'max_('),
        (r'\\bdabs\\s*\\(', 'fabs('),
        (r'\\bdsqrt\\s*\\(', 'sqrt('),
        (r'\\bdexp\\s*\\(', 'exp('),
        (r'\\bdlog\\s*\\(', 'log('),
        (r'\\bdsin\\s*\\(', 'sin('),
        (r'\\bdcos\\s*\\(', 'cos('),
        (r'\\bdatan2\\s*\\(', 'atan2('),
        (r'\\bdmod\\s*\\(', 'fmod('),
        (r'\\bint\\s*\\(', 'floor('),
        (r'\\bnint\\s*\\(', 'round('),
        (r'\\bdble\\s*\\(', '('),
        (r'\\bcmplx\\s*\\(', 'CMPLX('),
        (r'\\bdcmplx\\s*\\(', 'DCMPLX('),
        (r'\\bdconjg\\s*\\(', 'conj('),
        (r'\\bdimag\\s*\\(', 'imag('),
        (r'\\bdreal\\s*\\(', 'real('),
        (r'\\bcall\\s+(\\w+)\\s*\\(([^)]*)\\)', r'\\1_(\\2);'),
        (r'\\bparameter\\s*\\(([^)]+)\\)', r'const double \\1'),
        (r'\\bdata\\s+(\\w+)\\s*/\\s*([^/]+)\\s*/', r'double \\1 = \\2;'),
        (r'\\bexternal\\s+(\\w+)', r'extern void \\1_();'),
        (r'\\bintrinsic\\s+(\\w+)', r'/* intrinsic \\1 */'),
        (r'\\bcommon\\s*/\\s*(\\w+)\\s*/\\s*([^!\\n]+)', r'/* common block \\1: \\2 */'),
        (r'\\bsave\\s+([^!\\n]+)', r'static \\1;'),
        (r'\\bimplicit\\s+none', r'/* implicit none */'),
        (r'\\bwrite\\s*\\(\\s*\\*\\s*,\\s*\\*\\s*\\)\\s*([^!\\n]+)', r'printf("%s\\n", \\1);'),
        (r'\\bread\\s*\\(\\s*\\*\\s*,\\s*\\*\\s*\\)\\s*([^!\\n]+)', r'scanf("%s", &\\1);'),
        (r'\\bstop', r'exit(0);'),
        (r'\\breturn', r'return;'),
        (r'\\bend', r'}'),
        (r'\\bfunction\\s+(\\w+)\\s*\\(([^)]*)\\)', r'double \\1_(\\2){'),
        (r'end\\s+function', r'}'),
        # Handle array dimensions with ranges like ims:ime
        (r'double\\s+(\\w+)(\\w+:\\w+,?)+;', r'double *\\1;'),
        (r'int\\s+(\\w+)(\\w+:\\w+,?)+;', r'int *\\1;'),
    ]
    
    # Read original file
    with open(filename, 'r') as f:
        content = f.read()
    
    # Apply substitutions
    for pattern, replacement in patterns:
        content = re.sub(pattern, replacement, content)
    
    # Write processed content back to original file
    with open(filename, 'w') as f:
        f.write(content)
    
    # Also write to a copy with .c extension
    c_filename = filename.replace('.F90', '.c')
    with open(c_filename, 'w') as f:
        f.write(content)
    
    # Additional processing for includes
    proc_pos_include(filename)
    
    # Debug output to check content
    print(f"Processed content written to {c_filename}")
    return content



def process_memory_operations(filename, varmap_lines, operation_type):
    operations = []
    for line in varmap_lines:
        var_match = re.match(r"(\w+)_mp_(\w+)_\((.*?)\)(\w+)", line.strip())
        if not var_match:
            continue
            
        var_type = "double" if "real" in line else "int"
        dims = var_match.group(3).replace(",", "*")
        cuda_op = ""
        
        if operation_type == "HtoD":
            cuda_op = f"CHECK(cudaMemcpy(d_{var_match.group(2)}, {var_match.group(1)}_mp_{var_match.group(2)}_, "\
                     f"{dims}*sizeof({var_type}), cudaMemcpyHostToDevice));"
        elif operation_type == "DtoH":
            cuda_op = f"CHECK(cudaMemcpy({var_match.group(1)}_mp_{var_match.group(2)}_, d_{var_match.group(2)}, "\
                     f"{dims}*sizeof({var_type}), cudaMemcpyDeviceToHost));"
        elif operation_type == "init":
            cuda_op = f"CHECK(cudaMalloc(&d_{var_match.group(2)}, {dims}*sizeof({var_type})));"
        elif operation_type == "finalize":
            cuda_op = f"CHECK(cudaFree(d_{var_match.group(2)}));"
        
        if cuda_op:
            operations.append(cuda_op)
    
    return operations

def handle_global_variables(filename):
    # 收集全局变量
    global_vars = []
    for h_file in Path("headfile").glob("*"):
        with open(h_file) as f:
            content = f.read()
            # 排除函数指针和复杂类型
            matches = re.findall(r"\b(?:double|int)\s+\*?\w+(?:\s*\[[^\]]*\])?;", content)
            global_vars.extend(matches)
    
    # 生成头文件内容
    header_content = [
        "#ifndef __{}_CU_H__".format(filename.upper()),
        "#define __{}_CU_H__".format(filename.upper()),
        "\n#include \"common.h\"\n"
    ]
    
    # 添加设备指针声明
    device_ptrs = []
    with open(f"{filename}_init.cu") as f:
        for line in f:
            if "cudaMalloc" in line:
                match = re.search(r"d_(\w+)", line)
                if match:
                    ptr_name = f"d_{match.group(1)}"
                    type_match = re.search(r"sizeof\((\w+)", line)
                    var_type = type_match.group(1) if type_match else "double"
                    header_content.append(f"extern {var_type}* {ptr_name};")
                    device_ptrs.append(ptr_name)
    
    # 添加全局变量
    header_content.append("\n// Global variables from Fortran")
    for var in global_vars:
        if not any(ptr in var for ptr in device_ptrs):
            header_content.append(f"extern {var.strip()}")
    
    header_content.append("\n#endif\n")
    
    # 写入头文件
    with open(f"{filename}_cu.h", "w") as f:
        f.write("\n".join(header_content))



def proc_headfile(file_list):
    # 处理头文件转换
    for f90_file in file_list:
        c_header = f90_file.with_suffix('.h')
        with open(f90_file) as src, open(c_header, 'w') as dst:
            content = src.read()
            # 转换变量声明
            content = re.sub(r'(?i)real\s*,\s*dimension\s*\(([^)]+)\)\s*::\s*(\w+)',
                           r'double \2[\1];', content)
            # 写入头文件保护
            dst.write(f'#ifndef _{c_header.name.upper()}_\n')
            dst.write(f'#define _{c_header.name.upper()}_\n\n')
            dst.write(content)
            dst.write('\n#endif\n')


def add_includes(filename):
    includes = set()
    with open(f"{filename}.cu") as f:
        content = f.read()
        matches = re.findall(r"\b(\w+)_mp_\w+\b", content)
        for mod in set(matches):
            includes.add(f"#include \"{mod}.h\"")
    
    with open(f"{filename}.cu", "r+") as f:
        content = f.read()
        new_content = "#include \"{}_cu.h\"\n#include \"common.h\"\n".format(filename)
        new_content += "\n".join(includes) + "\n\n" + content
        f.seek(0)
        f.write(new_content)





def log_error(message):
    with open('tmp/error_log', 'a') as log:
        log.write(message + '\n')

def main():
    if len(sys.argv) < 2:
        print("Usage: python script.py <input_file.f90>")
        sys.exit(1)

    # Create output directory
    os.makedirs('output', exist_ok=True)

    # Get base filename
    input_file = sys.argv[1]
    filename = os.path.splitext(os.path.basename(input_file))[0]
    f_file = filename + '.F90'
    
    # Define obj_path here to fix undefined variable error
    obj_path = os.path.join('output', f_file)

    # Rename .f90 to .F90 if needed
    for fname in glob('*.f90'):
        try:
            new_name = fname.replace('.f90', '.F90')
            os.rename(fname, new_name)
        except Exception as e:
            log_error(f"Rename error {fname}: {str(e)}")

    # Copy input file to tmp if it's not already there
    try:
        if not os.path.samefile(input_file, obj_path):
            shutil.copy(input_file, 'output')
    except Exception as e:
        log_error(f"Copy error {input_file}: {str(e)}")

    for h_file in glob('*.h'):
        try:
            shutil.copy(h_file, 'output')
        except Exception as e:
            log_error(f"Copy error {h_file}: {str(e)}")

    # Execute processing pipeline
    processing_steps = [
        lambda _: preprocess(obj_path),
        lambda _: proc_real_dim(obj_path),
        lambda _: proc_find_call(obj_path),
        lambda _: proc_find_allvar(obj_path),
        lambda _: proc_allocate(f_file),
        lambda _: proc_varfile_map(f_file),
        lambda _: proc_varname(f_file),
        lambda _: proc_do(f_file),
        lambda _: proc_f2c(obj_path),  
        lambda _: proc_headfile([])  # Empty list as placeholder
    ]

    for step in processing_steps:
        try:
            step(obj_path)
        except Exception as e:
            log_error(f"Error in {step.__name__}: {str(e)}")
            break

    # Cleanup temporary files, keep only the output C file
    cleanup_temp_files(filename)

def cleanup_temp_files(filename):
    """Remove temporary files generated during processing, keeping only the output C file."""
    output_c_file = os.path.join('output', filename + '.c')
    for file_path in glob(os.path.join('output', filename + '*')):
        if file_path != output_c_file:
            try:
                os.remove(file_path)
                print(f"Removed temporary file: {file_path}")
            except Exception as e:
                log_error(f"Error removing {file_path}: {str(e)}")
    # Also remove error_log if it exists
    error_log_path = os.path.join('output', 'error_log')
    if os.path.exists(error_log_path):
        try:
            os.remove(error_log_path)
            print(f"Removed error log: {error_log_path}")
        except Exception as e:
            log_error(f"Error removing error log: {str(e)}")

if __name__ == '__main__':
    main()


